﻿using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

namespace MiniTools;

public class TypeWriter
{
    public static void Main()
    {
        new TypeWriter().ShowTxt();
    }

    public int Test()
    {
        return 1;
    }
    
    const string T_COLOR = "color";
    const string T_SIZE = "size";
    const string T_B = "b";

    Regex _regexColor = new Regex("<(color)=(.*?)>(.*?)</color>");
    Regex _regexSize = new Regex("<(size)=(.*?)>(.*?)</size>");
    Regex _regexB = new Regex("<(b)>(.*?)</b>");

    StringBuilder _sb = new StringBuilder();
    MatchCollection _collectionColor;
    MatchCollection _collectionSize;
    MatchCollection _collectionB;

    int showTxtIndex = 0;
    int txtLength = 0;
    
    const string targetTxt = "大家好，我是<color=#EA5B44FF><size=40>新abc发</size></color>，感谢大家的<size=40>关abc注</size>与<b>支abc持</b>。";

    public void ShowTxt(string txt = targetTxt)
    {
        _collectionColor = _regexColor.Matches(txt);
        _collectionSize = _regexSize.Matches(txt);
        _collectionB = _regexB.Matches(txt);

        txtLength = txt.Length;

        StartTypeWrite(txt);
    }

    private void StartTypeWrite(string txt)
    {
        while (showTxtIndex < txtLength)
        {
            _sb.Clear();

            bool isEndRefresh = showTxtIndex == txtLength - 1;

            Match _match = GetCurMatchGroup(showTxtIndex);

            for (int i = 0; i < txtLength; i++)
            {
                if (_match == null)
                {
                    if (i > showTxtIndex)
                    {
                        SetShowTxtIndex(i);
                        break;
                    }

                    _sb.Append(txt[i]);
                }
                else
                {
                    if (i < _match.Index)
                    {
                        _sb.Append(txt[i]);
                    }
                    else if (i == _match.Index)
                    {
                        // 查找要显示的文字下标
                        Group _groupParam = GetMatchParamGroup(_match);
                        switch (_match.Groups[1].Value)
                        {
                            case T_COLOR:
                                i += 6 + _groupParam.Length + 1;
                                _sb.AppendFormat("<color={0}>", _groupParam);
                                break;
                            case T_SIZE:
                                i += 5 + _groupParam.Length + 1;
                                _sb.AppendFormat("<size={0}>", _groupParam);
                                break;
                            case T_B:
                                i += 2;
                                _sb.Append("<b>");
                                break;
                            default:
                                break;
                        }
                    }
                    else
                    {
                        // 在当前正则匹配的显示范围内
                        if (i > showTxtIndex)
                        {
                            SetShowTxtIndex(i);
                            switch (_match.Groups[1].Value)
                            {
                                case T_COLOR:
                                    _sb.Append("</color>");
                                    break;
                                case T_SIZE:
                                    _sb.Append("</size>");
                                    break;
                                case T_B:
                                    _sb.Append("</b>");
                                    break;
                                default:
                                    break;
                            }

                            break;
                        }

                        _sb.Append(txt[i]);
                    }
                }

                if (isEndRefresh)
                {
                    showTxtIndex++;
                }
            }

            Console.WriteLine(_sb.ToString());
        }
    }

    void SetShowTxtIndex(int index)
    {
        showTxtIndex = index;
        Match _match = GetCurMatchGroup(showTxtIndex);
        if (_match == null)
        {
            return;
        }

        Group _groupParam = GetMatchParamGroup(_match);
        Group _groupContent = GetMatchContentGroup(_match);
        int curMatchShowMinIndex = 0;
        int curMatchShowMaxIndex = 0;
        int endSimbolLength = 0;
        switch (_match.Groups[1].Value)
        {
            case T_COLOR:
                endSimbolLength = 8;
                curMatchShowMinIndex = _match.Index + 6 + _groupParam.Length + 1 + 1;
                curMatchShowMaxIndex = _match.Index + 6 + _groupParam.Length + 1 + _groupContent.Length;
                break;
            case T_SIZE:
                endSimbolLength = 7;
                curMatchShowMinIndex = _match.Index + 5 + _groupParam.Length + 1 + 1;
                curMatchShowMaxIndex = _match.Index + 5 + _groupParam.Length + 1 + _groupContent.Length;
                break;
            case T_B:
                endSimbolLength = 4;
                curMatchShowMinIndex = _match.Index + 2 + 1;
                curMatchShowMaxIndex = _match.Index + 2 + _groupContent.Length;
                break;
            default:
                // CoreUtils.logService.Error("expr");
                return;
                break;
        }

        if (showTxtIndex < curMatchShowMinIndex)
        {
            showTxtIndex = curMatchShowMinIndex;
        }
        else if (showTxtIndex > curMatchShowMaxIndex)
        {
            showTxtIndex = curMatchShowMaxIndex + endSimbolLength + 1;
        }
    }

    Match GetCurMatchGroup(int index)
    {
        for (int i = 0; i < _collectionSize.Count; i++)
        {
            Match _match = _collectionSize[i];
            if (index >= _match.Index && index < _match.Index + _match.Length)
            {
                return _match;
            }
        }

        for (int i = 0; i < _collectionColor.Count; i++)
        {
            Match _match = _collectionColor[i];
            if (index >= _match.Index && index < _match.Index + _match.Length)
            {
                return _match;
            }
        }

        for (int i = 0; i < _collectionB.Count; i++)
        {
            Match _match = _collectionB[i];
            if (index >= _match.Index && index < _match.Index + _match.Length)
            {
                return _match;
            }
        }

        return null;
    }

    Group GetMatchParamGroup(Match _match)
    {
        switch (_match.Groups[1].Value)
        {
            case T_COLOR:
            case T_SIZE:
                if (_match.Groups.Count < 3)
                {
                    //CoreUtils.logService.Error("expr");
                    return null;
                }

                return _match.Groups[2];
                break;
            case T_B:
                return null;
                break;
            default:
                // CoreUtils.logService.Error("expr");
                return null;
                break;
        }
    }

    Group GetMatchContentGroup(Match _match)
    {
        switch (_match.Groups[1].Value)
        {
            case T_COLOR:
            case T_SIZE:
                if (_match.Groups.Count < 4)
                {
                    //CoreUtils.logService.Error("expr");
                    return null;
                }

                return _match.Groups[3];
                break;
            case T_B:
                if (_match.Groups.Count < 3)
                {
                    //CoreUtils.logService.Error("expr");
                    return null;
                }

                return _match.Groups[2];
                return null;
                break;
            default:
                // CoreUtils.logService.Error("expr");
                return null;
                break;
        }
    }
}